/**
 * @file ApplicationLayer.cpp
 * @Synopsis
 * @author Mingyu Wu
 * @version 1.0.0
 * @date 2024-04-22
 */

#include "./include/ApplicationLayer.h"

std::shared_ptr<ApplicationLayer> ApplicationLayer::instance = nullptr;

ApplicationLayer::ApplicationLayer() {
    db = std::make_shared<DataBase>();
    hashTab.clear();
}

ApplicationLayer::~ApplicationLayer() {}

int ApplicationLayer::Init() { return db->Init(); }

int ApplicationLayer::QueryData(
    std::unordered_map<std::string, std::string> &readData) {
    if (!db->IsServerOnline()) {
        if (ErrorInfo::OK != db->Init()) {
            return ErrorInfo::REDIS_OFFLINE;
        }
    }

    hashGroupSet.clear();
    StoreQueryFields.clear();

    XXH64_hash_t hash;
    int          group = 0;

    // 使用迭代器进行遍历和操作
    for (auto it = readData.begin(); it != readData.end();) {
        if (it->first.empty()) {
            it = readData.erase(it); // 使用返回的迭代器更新迭代器位置
        }
        else {
            hash = XXH64(
                it->first.c_str(), it->first.size(), Configuration::HASHSEED);

            group = hash % Configuration::dataConf.begin()->HashGroupCount;
            auto insertSuccess = hashGroupSet.insert(group);
            StoreQueryFields[Configuration::dataConf.begin()->HashKeyPrefix +
                             std::to_string(group)]
                .insert(*it);
            ++it;
        }
    }

    zlog_i("QueryData: 查询 %ld hash Table", hashGroupSet.size());

    return this->CommitQuery(readData);
}

int ApplicationLayer::CommitQuery(
    std::unordered_map<std::string, std::string> &readData) {
    std::map<std::string,
             std::unordered_map<std::string, std::string>>::iterator hashIter;
    std::unordered_map<std::string, std::string>                     reply;

    for (hashIter = StoreQueryFields.begin();
         hashIter != StoreQueryFields.end();
         hashIter++) {
        // 遍历hashkey
        //                          返回的map
        db->QueryData(hashIter->first, reply);
        std::this_thread::sleep_for(std::chrono::milliseconds(5));
        if (0 == reply.size()) {
            zlog_w("%s  查询数据无效", hashIter->first.c_str());
            return ErrorInfo::DATA_NULL;
        }
        for (auto &kvPair : StoreQueryFields[hashIter->first]) {
            auto it = reply.find(kvPair.first);
            if (it != reply.end()) {
                readData[kvPair.first] = reply[kvPair.first];
            }
            else {
                zlog_w("%s 字段错误", kvPair.first.c_str());
            }
        }
    }
    return ErrorInfo::OK;
}

int ApplicationLayer::SendControlData(
    std::string                                       whichCCU,
    std::vector<std::pair<std::string, std::string>> &writeData) {

    // 选择发送到哪个Streamkye
    const std::unordered_map<std::string, std::string> sendWhichCCU = {
        {"CCU1", "Stream:CCU1"},
        {"CCU2", "Stream:CCU2"},
        {"CCU3", "Stream:CCU3"},
    };

    std::string streamKey = sendWhichCCU.find(whichCCU)->second;

    std::vector<std::pair<std::string, std::string>>::iterator iter;
    for (iter = writeData.begin(); iter < writeData.end(); iter++) {

        // 排除键和值是""的可能性
        if (iter->second.empty() || iter->first.empty()) {
            zlog_w("下发控制参数:%s 值为空", iter->first.c_str());
            iter = writeData.erase(iter);
        }
    }

    return db->StreamSend(streamKey, writeData);
}

std::shared_ptr<ApplicationLayer> ApplicationLayer::GetInstance() {
    if (instance == nullptr) {
        instance = std::make_shared<ApplicationLayer>();
    }
    return instance;
}
